#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>

#include "Utils.h"
#include "base64.h"

/* ****************
 * WARNING!!!
 * These two function may cause MEMORY LEAK!!!
 * They should be modified to use a parameters to save the result
**************** */
wchar_t* GBKToUnicode(const char* szGBString)
{
        int nLength=MultiByteToWideChar(CP_UTF8,0,szGBString,-1,NULL,0);
        wchar_t* pBuffer = malloc(sizeof(wchar_t)*(nLength+1));
        MultiByteToWideChar(CP_UTF8,0,szGBString,-1,pBuffer,nLength);
        pBuffer[nLength]=0;
        return pBuffer;
}

char* UnicodeToGBK(const wchar_t* szUnicodeString)
{
        int nLength=WideCharToMultiByte(CP_UTF8,0,szUnicodeString,-1,NULL,0,NULL,NULL);
        char* pBuffer=malloc(sizeof(char)*(nLength+1));
        WideCharToMultiByte(CP_UTF8,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);
        pBuffer[nLength]=0;
        return pBuffer;
}

/************************************************************************/
/* Can these two function works???                                      */
/************************************************************************/
int Lua_UnicodeToGBK(lua_State *L){
	const char *src = lua_tostring(L,1);
	char *dest;

	dest = UnicodeToGBK(src);
	lua_pushstring(L,dest);
	return 1;
}
int Lua_GBKToUnicode(lua_State *L){
	const char *src = lua_tostring(L,1);
	char *dest;
	dest = GBKToUnicode(src);
	lua_pushstring(L,dest);
	return 1;
}

int Lua_System(lua_State *L){
	int r;
	const char *cmd = lua_tostring(L,1);
	const char *para = lua_tostring(L,2);
	DWORD wait = lua_tointeger(L,3);

	SHELLEXECUTEINFO ShExecInfo = {0};

	if(wait == -1) wait = INFINITE;

	printf("DBG:Function Lua_System() in Utils.c\n");
	printf("DBG:cmd = \"%s\" para = \"%s\"\n",cmd,para);
	
	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
	ShExecInfo.hwnd = NULL;
	ShExecInfo.lpVerb = NULL;
	ShExecInfo.lpFile = GBKToUnicode(cmd);
	ShExecInfo.lpParameters = GBKToUnicode(para);
	ShExecInfo.lpDirectory = NULL;
	ShExecInfo.nShow = SW_SHOW;
	ShExecInfo.hInstApp = NULL;
	r = ShellExecuteEx(&ShExecInfo);

	lua_pushnumber(L,r);

	WaitForSingleObject(ShExecInfo.hProcess,wait);

	return 1;
}

int Lua_MessageBox(lua_State *L){
	char* msg;
	char* title;
	long type;
	int r;

	if(!(lua_isstring(L,1) && lua_isstring(L,2) && lua_isnumber(L,3))){
		lua_pushstring(L,"Invaild para");
		return 0;
	}

	msg = lua_tostring(L,1);
	title = lua_tostring(L,2);
	type = (long)lua_tonumber(L,3);	//TODO:This para took no effect!
	switch(type){
		case 1:
			type = MB_OK;
			break;
		case 2:
			type = MB_YESNO;
			break;
		default:
			type = MB_OK;
	}

	r = MessageBox(NULL,GBKToUnicode(msg),GBKToUnicode(title),type);
	lua_pushnumber(L,r);

	return 1;
}

int luaopen_Library_Utils_Utils_lib(lua_State *L){
	static const struct luaL_Reg Utils [] = {
		{"Lua_MessageBox",Lua_MessageBox},
		{"Lua_System",Lua_System},
		{"Lua_Base64_Encode",base64_encode},
		{"Lua_Base64_Decode",base64_decode},
		{"Lua_UnicodeToGBK",Lua_UnicodeToGBK},
		{"Lua_GBKToUnicode",Lua_GBKToUnicode},
		{NULL,NULL}
	};
	luaL_register(L,"Library_Utils_Utils_lib",Utils);
	return 1;
}